#include "cudpcmd.h"
#include <QFile>
#include <QList>
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "serversetting.h"
#include "module/cnetworkthread.h"
#include "control/cknxcontrol.h"
/////////////////////////////////////////////////////////////////////////
/// \brief CUdpCmd::CUdpCmd
/// \param parent

void * CUdpCmd::cntDelegate = NULL;

CUdpCmd::CUdpCmd(QThread *parent) :
    QThread(parent)
{
    _curDT = QDateTime::currentDateTime();
    _curHour = QTime::currentTime().hour();
    _muc_update = false;
}

void CUdpCmd::ready(int port)
{
    udp = new QUdpSocket();
    _muc_udp = new QUdpSocket();

    if(!udp->bind(QHostAddress("0.0.0.0"),port))// || !_muc_udp->bind(QHostAddress("0.0.0.0"),5100) )
    {
        qDebug() << QString("UDP: bind port fail: %1").arg(port);
        qDebug() << "App still running ???";
    }
    else
    {
        connect(udp,SIGNAL(readyRead()),this,SLOT(readDataSocket()));
        //connect(_muc_udp,SIGNAL(readyRead()),this,SLOT(mucReadDataSocket()));
    }


    //qDebug() << "splitData:" << splitData("TG+OK\r\nTG+ABCD\r\nTG+12345\r\nTG+UPD00\r\n","TG+");
}

void CUdpCmd::init_watch_dog()
{
}

int CUdpCmd::find_head(char *buf,int size)
{
    for(int i=0;i<size-1;i++)
    {
        if(buf[i]==0xaa && buf[i+1] == 0x55 )
            return i;
    }

    return -1;
}

void CUdpCmd::mucUpdate(QByteArray d)
{
    char *szBuf = d.data();
    int size = d.size();
    if(size< 20)
        return;

    qDebug() << "tty  read data:  \n " <<  size  << ":" <<d.toHex();

    int start_index = find_head(szBuf,size);
    if(start_index > 0)
    {
        int h =( (int)szBuf[start_index-2]) &0xff;
        int l = ((int)szBuf[start_index-1] )& 0xff;

        int rsize =  (h <<8)|l;

       if(size > start_index + rsize)
        {
            QByteArray d(&szBuf[start_index],rsize);

            qDebug() << "tty send read hex data:  \n " <<  " (" << rsize << ") " << d.toHex();

            _muc_udp->writeDatagram(d,QHostAddress(_ip_mcu),_port_mcu);

        }
        else if(_muc_update)
        {
            qDebug() << "tty read data format error ! ";
        }
    }
    else
    {
        qDebug() << "mcu update tag no found : " <<  d.toHex();
    }
}

QList<QByteArray> CUdpCmd::splitData(QByteArray data,QByteArray sp)
{
    QList<QByteArray> list;

    int next  = -1;
    int index = data.indexOf(sp);
    while(index>=0)
    {
        next = data.indexOf(sp,index+sp.size());
        if(next>0)
        {
            QByteArray d = data.mid(index,next-index);
            list.append(d);

            data = data.mid(next,data.length()-next);
        }
        else
        {
            list.append(data);
            break;
        }

        index = data.indexOf(sp);
    }

    return list;
}

void CUdpCmd::run(){
}

void CUdpCmd::doDogTimeout()
{

}

void CUdpCmd::writeSerial(QByteArray d)
{

}

void CUdpCmd::doRunStream()
{

}

void CUdpCmd::doStopStream()
{

}

void CUdpCmd::check_update()
{

}

void CUdpCmd::checkUpdateVersion()
{

}

void CUdpCmd::doUpdateMessage(QByteArray data)
{

}

void CUdpCmd::updateDownloadWithId(int id,int version,int filesize)
{

}

void CUdpCmd::updateDownload(QString filename,int filesize)
{

}

void CUdpCmd::doTimeout()
{

}

void CUdpCmd::reGetSystemTime(int server_hour)
{
    _curHour = server_hour;
}

void CUdpCmd::syncFileSystem()
{
    QString cmd = "/bin/sync";
    QStringList arg;
    execCMD(cmd,arg);
}

void CUdpCmd::checkKNX()
{
    if(cntDelegate == NULL)
    {
        qDebug() << "CHECK KNX: fail by null object!";
        return ;
    }

    CKnxExecThread *eThread = new CKnxExecThread();
    eThread->ttgConnector = (CTTGIpsConnector *)cntDelegate;

    connect(eThread,SIGNAL(finished()),eThread,SLOT(deleteLater()));

    QString sendAddress,sendValue;
    DATA_TYPE sendDataType;
    DATA_DEFINE sendValueDefine;

    char _data_buf[1] = {0x1};

    CExecStruct *s = new CExecStruct();
    s->address = "1/1/1";
    s->type = ONE_BIT_VALUE;
    s->data = QByteArray((const char *)_data_buf,1);

    eThread->execList.append(s);
    eThread->start();
}

void CUdpCmd::mucReadDataSocket()
{

}

void CUdpCmd::readSerialData()
{

}

void CUdpCmd::checkRTSPmode(QString mode)
{

}

void CUdpCmd::readDataSocket()
{
    QByteArray cmdBytes;
    QHostAddress peerAddr;
    unsigned short port;

    if (udp->hasPendingDatagrams())
    {
        cmdBytes.resize(udp->pendingDatagramSize());
        udp->readDatagram(cmdBytes.data(),cmdBytes.size(),&peerAddr,&port);

        port =9999;

        QStringList cmdlist = QString(cmdBytes).split("::");
        if(cmdlist.size() >1)
        {
            if(cmdlist.at(0).startsWith("VERSION"))
            {
                QString verison = QString("--- TTG-GateWay --- \n Version %1 \n Serial %2 \n Network: %3")
                        .arg(g_version)
                        .arg(ServerSetting::defaultSetting()->_serial)
                        .arg(CNetworkThread::gServerConnected?"ok":"error");

                udp->writeDatagram(verison.toLocal8Bit(),peerAddr,port);

                checkKNX();
            }
            else if(cmdlist.at(0) == "READ")
            {
                QByteArray d = readFile(cmdlist.at(1));
                udp->writeDatagram(d,peerAddr,port);
            }
            else if(cmdlist.at(0) == "WRITE")
            {
                if(cmdlist.size()>2)
                {
                    QByteArray d = writeFile(cmdlist.at(1),cmdlist.at(2));
                    syncFileSystem();

                    udp->writeDatagram(d,peerAddr,port);

                    if(cmdlist.at(1).contains("config.ini"))
                    {
                        if(cmdlist.at(2).contains("stream2"))
                        {
                            checkRTSPmode("S3NEWCAP_HDR480p");
                        }
                        else
                        {
                            checkRTSPmode("S3NEWCAP_HDR");
                        }
                    }
                }
            }
            else if(cmdlist.at(0) == "REBOOT")
            {
                udp->writeDatagram("reboot",peerAddr,port);
                doReboot();
            }
            else if(cmdlist.at(0) == "SOUND")
            {
                if(cmdlist.size() > 1)
                {
                    QString cmd = "amixer";
                    QStringList arg;
                    arg << "set" << "Master" << cmdlist.at(1);

                    udp->writeDatagram("sound ok",peerAddr,port);

                    execCMD(cmd,arg);
                }
            }
            else if(cmdlist.at(0) == "DATE")
            {
                if(cmdlist.size() > 1)
                {
                    QString cmd = "date";
                    QStringList arg;
                    arg << "-s" << cmdlist.at(1);

                    udp->writeDatagram("date ok",peerAddr,port);

                    execCMD(cmd,arg);
                }
            }
        }
    }
}

void CUdpCmd::doReboot()
{

}

QByteArray CUdpCmd::readFile(QString fileName)
{
    QFile f(fileName);
    QByteArray d;
    if(f.open(QFile::ReadOnly))
    {
        d = f.readAll();
        f.close();
    }

    return d;
}

QByteArray CUdpCmd::writeFile(QString fileName,QString data)
{
    QFile f(fileName);
    if(f.open(QFile::ReadWrite))
    {
        f.resize(0);
        f.write(data.toLocal8Bit());
        f.close();

        return "ok";
    }

    return "fail";
}

void CUdpCmd::execCMD(QString command,QStringList arg)
{
    qDebug() << "exec cmd: " << command << arg;

    QString cmd= command;
    _pro.start(cmd,arg);

    _pro.waitForFinished(6000);

    qDebug() <<"exec result:" << _pro.readAllStandardOutput()  << " ||||" << _pro.readAllStandardError();

}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CTcpUpdateServer::CTcpUpdateServer(QObject *parent) :
    QTcpServer(parent)
{
    setMaxPendingConnections(1);
    connect(this,SIGNAL(newConnection()),this,SLOT(doNewConnect()));
}

void CTcpUpdateServer::ready(int port)
{
    if(!this->listen(QHostAddress::Any,port))
        qDebug() << "Update Server bind error!";
}

void CTcpUpdateServer::doNewConnect()
{
    qDebug() << "Update: new connect";
    QTcpSocket *s = this->nextPendingConnection();
    if(s->waitForReadyRead(3000))
    {
        QByteArray d = s->readAll();
        QStringList cmdlist = QString(d).split("::");
        if(cmdlist.size() >2)
        {
            if(cmdlist.at(0).startsWith("UPDATE"))
            {
                QString fn = cmdlist.at(1);
                unsigned int length = cmdlist.at(2).toUInt();

                qDebug() << "Update: " << fn << " " << length;

                if(length < 1024*1024*10)
                {
                    char *buffer = (char *)malloc(length);
                    unsigned int read = 0 , index = 0,read_length = length;
                    while (read_length > 0 && s->waitForReadyRead(2000)) {
                        read = s->read(buffer+index,read_length);
                        index += read;
                        read_length -= read;
                    }

                    if(read_length == 0)
                    {
                        QFile f(fn);
                        if(f.open(QFile::ReadWrite))
                        {
                            f.resize(0);
                            f.write(buffer,length);
                            f.close();
                        }
                    }
                    else
                    {
                        qDebug() << "Update:  fail " << index << " != " << length;
                    }

                    free(buffer);
                }
            }
        }

        s->disconnectFromHost();
        //s->deleteLater();

    }
}
